package main

//import (
//	"bytes"
//	"fmt"
//	"io"
//	"os"
//	"os/exec"
//	"path/filepath"
//	"sync"
//	"time"
//
//	"golang.org/x/text/encoding/simplifiedchinese"
//	"golang.org/x/text/transform"
//)
//
//// 假设的结构体和函数定义
//type Task struct {
//	Workspace string
//	LogPath   string
//	Status    string
//	Command   string
//}
//
//type Request struct {
//	ExecuteID string
//	NodeUuid  string
//	ServerIP  string
//}
//
//type Setting struct {
//	ServerIP  string
//	IsWindows bool
//}
//
//var setting = Setting{
//	ServerIP:  "your_server_ip",
//	IsWindows: os.PathSeparator == '\\',
//}
//
//func createWorkspace(id string) string {
//	// 模拟创建工作空间
//	return "workspace_" + id
//}
//
//// createScriptFile 根据命令内容创建对应的脚本文件
//func createScriptFile(workspace, command, nodeUuid string) (string, error) {
//	// 检查 workspace 路径是否存在
//	if _, err := os.Stat(workspace); os.IsNotExist(err) {
//		return "", fmt.Errorf("指定的工作区路径不存在: %s", workspace)
//	}
//
//	scriptName := fmt.Sprintf("script_%s", nodeUuid)
//	if setting.IsWindows {
//		scriptName += ".bat"
//	} else {
//		scriptName += ".sh"
//	}
//
//	scriptPath := filepath.Join(workspace, scriptName)
//
//	// 根据操作系统创建不同类型的脚本
//	var scriptContent string
//	if setting.IsWindows {
//		// Windows批处理脚本
//		scriptContent = fmt.Sprintf(`@echo off
//setlocal
//%s
//`, command)
//	} else {
//		// Linux shell脚本
//		scriptContent = fmt.Sprintf(`#!/bin/bash
//%s
//`, command)
//	}
//
//	// 写入脚本内容
//	err := os.WriteFile(scriptPath, []byte(scriptContent), 0755)
//	if err != nil {
//		return "", fmt.Errorf("创建脚本文件失败: %v", err)
//	}
//
//	fmt.Printf("创建脚本文件: %s\n内容:\n%s\n", scriptPath, scriptContent)
//	return scriptPath, nil
//}
//
//func prepareCommand(scriptPath string) (*exec.Cmd, error) {
//	var cmd *exec.Cmd
//	if setting.IsWindows {
//		// 执行Windows批处理脚本
//		cmd = exec.Command("cmd", "/C", scriptPath)
//	} else {
//		// 执行Linux shell脚本
//		cmd = exec.Command("bash", scriptPath)
//	}
//
//	// 设置环境变量
//	cmd.Env = os.Environ()
//	cmd.Env = append(cmd.Env, fmt.Sprintf("GITEA_RUNNER=true"))
//
//	return cmd, nil
//}
//
//func tailLog(logPath, serverIP, executeID string, port int, stopChan chan struct{}) {
//	file, err := os.Open(logPath)
//	if err != nil {
//		fmt.Printf("打开日志文件失败: %v\n", err)
//		return
//	}
//	defer file.Close()
//
//	// 移动文件指针到文件末尾
//	_, err = file.Seek(0, io.SeekEnd)
//	if err != nil {
//		fmt.Printf("移动文件指针失败: %v\n", err)
//		return
//	}
//
//	buffer := make([]byte, 1024)
//	for {
//		select {
//		case <-stopChan:
//			// 接收到停止信号，等待一段时间确保所有日志都已写入
//			time.Sleep(500 * time.Millisecond)
//
//			// 继续读取剩余日志
//			for {
//				n, err := file.Read(buffer)
//				if n > 0 {
//					fmt.Print(string(buffer[:n]))
//				}
//				if err == io.EOF {
//					break
//				}
//				if err != nil {
//					fmt.Printf("读取日志失败: %v\n", err)
//					break
//				}
//			}
//			fmt.Println("没有更多日志内容，发送执行完成消息")
//			return
//		default:
//			n, err := file.Read(buffer)
//			if n > 0 {
//				fmt.Print(string(buffer[:n]))
//			}
//			if err == io.EOF {
//				time.Sleep(200 * time.Millisecond) // 减少等待时间，提高响应性
//				continue
//			}
//			if err != nil {
//				fmt.Printf("读取日志失败: %v\n", err)
//				return
//			}
//		}
//	}
//}
//
//// 自定义Writer，用于将输出同时写入日志文件和控制台
//type ConsoleAndLogWriter struct {
//	logFile *os.File
//}
//
//func (w *ConsoleAndLogWriter) Write(p []byte) (n int, err error) {
//	// 先在控制台打印
//	fmt.Print(string(p))
//
//	// 再写入日志文件
//	return w.logFile.Write(p)
//}
//
//func main() {
//	task := Task{
//		// 使用 && 连接的命令
//		Command: "gcc --version && cd /d C:\\Users\\wangzw\\.ops\\klocktestproxy\\c && echo \" start test temp\" && echo %TEMP% && kwinject --version && kwinject --output C:\\Users\\wangzw\\.ops\\klocktestproxy\\c\\kwinject.out E:\\klocwork12.3-windows\\msys64\\mingw64\\bin\\gcc  demo.c -o demo.exe && kwadmin create-project klocktestproxy && kwbuildproject --url http://192.168.0.131:8085/klocktestproxy -f -o table kwinject.out && kwadmin --url http://192.168.0.131:8085 load klocktestproxy table",
//	}
//
//	task.Workspace = createWorkspace("123")
//	task.LogPath = filepath.Join(task.Workspace, "run.log")
//	task.Status = "running"
//
//	fmt.Println("logpath     ", task.LogPath)
//	fmt.Println("workspace     ", task.Workspace)
//
//	// 创建用于停止日志读取的通道
//	stopChan := make(chan struct{})
//
//	// 创建用于通知主线程日志读取完成的通道
//	doneChan := make(chan struct{})
//
//	// 创建用于等待所有goroutine完成的WaitGroup
//	var wg sync.WaitGroup
//
//	// 创建临时脚本文件
//	scriptPath, err := createScriptFile(task.Workspace, task.Command, "node_uuid")
//	if err != nil {
//		handleError(&task, err)
//		return
//	}
//	fmt.Println(scriptPath)
//	//defer os.Remove(scriptPath) // 执行后删除脚本
//
//	// 启动日志读取协程
//	logFile, err := os.Create(task.LogPath)
//	if err != nil {
//		handleError(&task, err)
//		return
//	}
//	defer logFile.Close()
//
//	// 准备命令执行对象
//	cmd, err := prepareCommand(scriptPath)
//	cmd.Dir = task.Workspace
//	fmt.Println("prepareCommand after ")
//	if err != nil {
//		handleError(&task, err)
//		return
//	}
//
//	var out bytes.Buffer
//
//	// 创建自定义Writer，用于同时写入控制台和日志文件
//	consoleAndLogWriter := &ConsoleAndLogWriter{logFile: logFile}
//
//	if os.PathSeparator == '\\' {
//		// Windows 系统：实时转换 GBK 到 UTF-8
//		stdout, err := cmd.StdoutPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准输出管道失败: %v\n", err))
//			return
//		}
//
//		stderr, err := cmd.StderrPipe()
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("获取标准错误管道失败: %v\n", err))
//			return
//		}
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(&task, err)
//
//			// 在返回前关闭停止通道，通知日志读取协程停止
//			close(stopChan)
//
//			// 等待日志读取协程完成
//			<-doneChan
//
//			return
//		}
//
//		// 使用锁保护内存缓冲区和文件写入操作
//		var mu sync.Mutex
//
//		// 增加等待组计数，表示有两个goroutine需要等待
//		wg.Add(2)
//
//		// 异步处理标准输出（实时转换）
//		go func() {
//			defer wg.Done()
//
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stdout, decoder)
//
//			// 使用流式读取和写入，而不是一次性读取所有内容
//			buffer := make([]byte, 4096)
//			for {
//				n, err := reader.Read(buffer)
//				if n > 0 {
//					mu.Lock()
//
//					// 先写入内存缓冲区
//					out.Write(buffer[:n])
//
//					// 再写入日志文件和控制台
//					_, err := consoleAndLogWriter.Write(buffer[:n])
//
//					mu.Unlock()
//					if err != nil {
//						mu.Lock()
//						logFile.WriteString(fmt.Sprintf("写入标准输出失败: %v\n", err))
//						mu.Unlock()
//						break
//					}
//				}
//				if err != nil {
//					if err != io.EOF {
//						mu.Lock()
//						logFile.WriteString(fmt.Sprintf("处理标准输出失败: %v\n", err))
//						mu.Unlock()
//					}
//					break
//				}
//			}
//		}()
//
//		// 异步处理标准错误（实时转换）
//		go func() {
//			defer wg.Done()
//
//			decoder := simplifiedchinese.GBK.NewDecoder()
//			reader := transform.NewReader(stderr, decoder)
//
//			// 使用流式读取和写入，而不是一次性读取所有内容
//			buffer := make([]byte, 4096)
//			for {
//				n, err := reader.Read(buffer)
//				if n > 0 {
//					mu.Lock()
//
//					// 先写入内存缓冲区
//					out.Write(buffer[:n])
//
//					// 再写入日志文件和控制台
//					_, err := consoleAndLogWriter.Write(buffer[:n])
//
//					mu.Unlock()
//					if err != nil {
//						mu.Lock()
//						logFile.WriteString(fmt.Sprintf("写入标准错误失败: %v\n", err))
//						mu.Unlock()
//						break
//					}
//				}
//				if err != nil {
//					if err != io.EOF {
//						mu.Lock()
//						logFile.WriteString(fmt.Sprintf("处理标准错误失败: %v\n", err))
//						mu.Unlock()
//					}
//					break
//				}
//			}
//		}()
//	} else {
//		// Linux/Mac 系统：直接使用 MultiWriter
//		cmd.Stdout = io.MultiWriter(&out, consoleAndLogWriter)
//		cmd.Stderr = io.MultiWriter(&out, consoleAndLogWriter)
//
//		// 启动命令
//		if err := cmd.Start(); err != nil {
//			logFile.WriteString(fmt.Sprintf("启动命令失败: %v\n", err))
//			handleError(&task, err)
//
//			// 在返回前关闭停止通道，通知日志读取协程停止
//			close(stopChan)
//
//			// 等待日志读取协程完成
//			<-doneChan
//
//			return
//		}
//	}
//
//	// 增加等待组计数，表示有一个goroutine需要等待
//	wg.Add(1)
//
//	go func() {
//		defer wg.Done()
//
//		tailLog(task.LogPath, setting.ServerIP, "execute_id", 8280, stopChan)
//		// 日志读取完成后发送通知
//		doneChan <- struct{}{}
//	}()
//
//	// 增加等待组计数，表示有一个goroutine需要等待
//	wg.Add(1)
//
//	// 异步等待命令完成
//	go func() {
//		defer wg.Done()
//
//		err := cmd.Wait() // 这将阻塞直到脚本及其所有子进程完成
//
//		if err != nil {
//			logFile.WriteString(fmt.Sprintf("命令执行出错: %v\n", err))
//			fmt.Printf("命令执行出错: %v\n", err)
//			// 可以在这里处理错误状态
//		} else {
//			logFile.WriteString("命令执行成功完成\n")
//			fmt.Println("命令执行成功完成")
//		}
//
//		// 无论成功或失败，都关闭停止通道
//		close(stopChan)
//	}()
//
//	// 等待所有goroutine完成
//	wg.Wait()
//
//	fmt.Println("命令执行完成，日志已以 UTF - 8 编码写入", task.LogPath)
//}
